/*
SteelNzb
Copyright (C) 2008  Wessel v. Staal

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "logger.h"
#include "global.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


typedef struct loggerActionListener
{
	logAction action;
	void* userData;
} loggerActionListener;

typedef struct loggerState
{
	loggerActionListener** listeners;
	int listenerCount;
} loggerState;

/**
	Creates logger
	@returns pointer to created logger
*/
void* logger_createLogger()
{
	loggerState* state=NULL;

	if ( (state = malloc(sizeof(loggerState))) == NULL )
	{
		perror("Logger::CreateLogger");
		exit(1);
	}

	memset(state, 0, sizeof(loggerState));
	
	return state;
}

/**
	Frees logger and associated resources. Userdata is not freed
	@param logger Pointer to logger
	@returns void
*/
void logger_freeLogger(void* logger)
{
	loggerState* state=logger;
	int i =0;

	for ( i=0; i<state->listenerCount;i++ )
	{
		if ( state->listeners[i] != NULL )
			free(state->listeners[i]);
	}

	free(state->listeners);
	free(state);
}

/**
	Logs message and posts to each attached listener
	@param logger The logger instance
	@param format The string format, like printf
	@param arg1 The first argument
	@param arg2 The second argument
	@param arg3 The third argument
	@returns void
*/
void logger_log(void* logger, char* format, char* arg1, char* arg2, char* arg3)
{
	char* msg = NULL;
	int i =0;

	loggerState* state= logger;

	/* make seperate buffer to make this function the owner */
	if ( (msg = malloc(LOG_MSG_SIZE)) == NULL )
	{
		perror("Logger::Log");
		exit(1);
	}


	sprintf(msg, format, arg1, arg2, arg3);

	for ( i=0; i<state->listenerCount;i++ )
	{
		if ( state->listeners[i] != NULL )
			state->listeners[i]->action(state->listeners[i]->userData, msg);
	}

	free(msg);
}

/**
	Removes listener
	@param logger The logger
	@param action The callback
	@returns void
*/
void logger_removeListener(void* logger, logAction action)
{
	int i =0;
	loggerState* state= logger;

	for ( i=0; i<state->listenerCount;i++ )
	{
		if ( state->listeners[i] != NULL && state->listeners[i]->action == action )
		{
			free(state->listeners[i]);
			state->listeners[i] = NULL;
		}
	}
}

/**
	Adds listener
	@param logger The logger
	@param action Callback
	@param userData Data passed with callback
	@returns void
*/
void logger_addListener(void* logger, logAction action, void* userData)
{
	loggerState* state= logger;
	loggerActionListener* listener = NULL;

	if ( (listener = malloc(sizeof(loggerActionListener))) == NULL )
	{
		perror("Logger::AddListener");
		exit(1);
	}

	if ( (state->listeners = realloc(state->listeners, sizeof(loggerActionListener*) * ++state->listenerCount) ) == NULL )
	{
		perror("Logger::AddListener");
		exit(1);
	}

	listener->action = action;
	listener->userData = userData;

	state->listeners[state->listenerCount-1] = listener;
}
